package com.springboot.aspect;

import com.springboot.annotation.OperationLogDetail;
import com.springboot.domain.OperationLog;
import com.springboot.service.OperationLogServiceI;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.InetAddress;
import java.util.Date;

@Component
@Aspect
public class OperationLogAspect {

    @Resource(name = "operationLogServiceI")
    private OperationLogServiceI olsi;


    /*
     *@Pointcut("execution(* com.springboot.service.*.*(..))")
     */
    @Pointcut("@annotation(com.springboot.annotation.OperationLogDetail)")
    public void operationLogPointCut(){}

    @Around("operationLogPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint){

        Object res = null;
        try {
            res = joinPoint.proceed();
        }catch (Throwable throwable){
            throwable.printStackTrace();
        }finally {
            //执行添加日志
            addOperationLog(joinPoint,res);
        }
        return res;
    }

    /**
     * 添加日志
     * @param joinPoint
     * @param res
     */
    public void addOperationLog(JoinPoint joinPoint,Object res){

        //获取会话session
        RequestAttributes ras = RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = null;
        HttpSession session = null;
        if(ras!=null){
            req = (HttpServletRequest) ras.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            session = req.getSession();
        }

        MethodSignature sign = (MethodSignature)joinPoint.getSignature();
        OperationLogDetail old = sign.getMethod().getAnnotation(OperationLogDetail.class);
        String operationUser = "";
        if(session!=null){
            operationUser = session.getAttribute("userId")+"";
        }
        Date operationTime = new Date();
        String ip = req.getRemoteAddr();//获取ip地址
        if(ip.equals("127.0.0.1")||ip.equals("0:0:0:0:0:0:0:1")){
            try {
                ip = InetAddress.getLocalHost()+"";
                String ips[] = ip.split("/");
                ip = ips[ips.length-1];
                System.out.println("MAC="+getMacAddress(ip));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        String operationType = old.type().getValue();
        String operationUnit = old.unit();

        OperationLog ol =
                new OperationLog(operationUser,operationTime,ip,
                        operationType,operationUnit);

        olsi.add(ol);

    }

    /**
     * 获取物理网卡地址Mac
     * @param ip
     * @return
     */
    public String getMacAddress(String ip){
        String str = "",mac = "";
        try {

            Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
            InputStreamReader isr = new InputStreamReader(p.getInputStream());
            LineNumberReader input = new LineNumberReader(isr);
            for(int i=1;i<100;i++) {
                str = input.readLine();
                //str = new String(str.getBytes("iso-8859-1"),"GBK");
                if(str != null){
                    if(str.indexOf("MAC")>1){
                        mac = str.substring(str.indexOf("MAC"),str.length());
                        String macs[] =mac.split("=");
                        mac = macs[macs.length-1];
                        break;
                    }
                }
            }
            input.close();
            isr.close();

        }catch (Exception e){
            e.printStackTrace();
        }

        return mac;
    }

    @Before("operationLogPointCut()")
    public void doBefor(){
        System.out.println(System.currentTimeMillis()+"-进入方法前执行......");
    }

    @After("operationLogPointCut()")
    public void doAfter(){
        System.out.println(System.currentTimeMillis()+"-方法完成后执行......");
    }

    @AfterThrowing("operationLogPointCut()")
    public void doAfterThrowing(){
        System.out.println("方法发生异常时执行......");
    }

    @AfterReturning(pointcut = "operationLogPointCut()",returning = "ret")
    public void doAfterReturning(Object ret){
        System.out.println("完成返回值后执行......");
        System.out.println("方法的返回值为:"+ret);
    }

}
